package ru.compft.web.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import ru.compft.common.services.UserService;
import ru.compft.common.utils.GlobalErrors;
import ru.compft.common.utils.GlobalConstants;
import ru.compft.web.beans.LoginFormBean;

import javax.annotation.Resource;
import java.io.Serializable;

/**
 * User: ASUS
 * Date: 07.06.12
 * Time: 0:49
 * Контроллер страницы входа в систему
 */
@Controller("loginController")
@Scope("session")
public class LoginController implements Serializable {
    private static final long serialVersionUID = -4563511205466235147L;

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    private static final String USER = "user";

    @Resource(name = "authenticationManager")
    private AuthenticationManager authenticationManager; //authentication manager located in  Spring config: /WEB-INF/authenticationContext-security.xml

    @Resource(name = "loginFormBeanValidator")
    private Validator validator;

    @Resource(name = "userService")
    private UserService userService;

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    @ModelAttribute(USER)
    public LoginFormBean init() {
        System.out.println("LoginController init ModelAttribute " + USER);
        return new LoginFormBean();
    }

    /**
     * Сабмит формы аутентификации
     *
     * @param formBean
     * @param result
     * @return
     */
    @RequestMapping(value = "/logon", method = RequestMethod.POST)
    public String login(@ModelAttribute(USER) LoginFormBean formBean, BindingResult result) {
        System.out.println("LoginController login " + formBean);
        // валидация
        validator.validate(formBean, result);

        // нет ошибок валидации - идем дальше
        if (!result.hasErrors()) {
            // если попали сюда, значит нужно очистить все текущие отображения модулей
//            currentView.clearAll();

            if (logger.isDebugEnabled()) {
                logger.debug("Cleared all current view modules from Authentication Form");
            }
            //simple token holder
            final Authentication authenticationRequestToken = createAuthenticationToken(formBean);
            //authentication action
            try {
                final Authentication authenticationResponseToken = authenticationManager.authenticate(authenticationRequestToken);
                SecurityContextHolder.getContext().setAuthentication(authenticationResponseToken);
                //ok, test if authenticated, if yes reroute
                if (authenticationResponseToken.isAuthenticated()) {
                    //lookup authentication success url, or find redirect parameter from login bean

//                    saveUserAsCurrent(formBean.getUserName());

                    // редирект на страницу по умолчанию
                    return GlobalConstants.REDIRECT + GlobalConstants.SLASH;
                }
            } catch (BadCredentialsException badCredentialsException) {
                result.reject(GlobalErrors.LOGIN_FAILED);
            } catch (LockedException lockedException) {
                result.reject(GlobalErrors.ACCOUNT_LOCKED);
            } catch (DisabledException disabledException) {
                result.reject(GlobalErrors.ACCOUNT_DISABLED);
            }
        }

        return GlobalConstants.LOGIN_VIEW;
    }

//    /**
//     * Найдем в БД и сохраним рользователя, как текущего в сессии
//     *
//     * @param login
//    todo пользователя можно получить через SecurityContextHolder.getContext()
//     */
//    private void saveUserAsCurrent(String login) {
//        // поскольку аутентификация прошла успешна, загрузим текущего пользователя в бин CurrentUser
//        // через UserService
//        final AppUser appUser = userService.findUserByLogin(login);
//        final UserBean userBean = new UserBean();
//        UserAdapter.copyToBean(appUser, userBean);
//
//        currentUser.setUser(userBean);
//    }

    private Authentication createAuthenticationToken(LoginFormBean loginFormBean) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(
                        loginFormBean.getUserName(),
                        loginFormBean.getPassword()
                );
        return usernamePasswordAuthenticationToken;
    }
}
